package com.neuralnoise.linkedin;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeSet;

import com.google.code.linkedinapi.client.LinkedInApiClient;
import com.google.code.linkedinapi.client.LinkedInApiClientFactory;
import com.google.code.linkedinapi.schema.Connections;
import com.neuralnoise.AbstractDriver;
import com.neuralnoise.LinkedInDB;
import com.neuralnoise.foaf.core.Person;
import com.neuralnoise.geo.GeoUtils;
import com.neuralnoise.geo.GeoUtils.ServiceType;
import com.neuralnoise.hibernate.geo.GeoLocation;
import com.neuralnoise.hibernate.linkedin.Profile;
import com.neuralnoise.hibernate.linkedin.User;

public class LinkedInDriver extends AbstractDriver<String> {

	private LinkedInProperties properties;

	private String consumerKey;
	private String consumerSecret;
	private String accessToken;
	private String tokenSecret;
	
	private LinkedInApiClientFactory factory;
	private LinkedInApiClient client;
	
	public LinkedInDriver(LinkedInProperties properties) {
		this.properties = properties;
		this.consumerKey = this.properties.getConsumerKey();
		this.consumerSecret = this.properties.getConsumerSecret();
		this.accessToken = this.properties.getAccessToken();
		this.tokenSecret = this.properties.getTokenSecret();
		this.factory = LinkedInApiClientFactory.newInstance(this.consumerKey, this.consumerSecret);
		this.client = this.factory.createLinkedInApiClient(this.accessToken, this.tokenSecret);
	}

	@Override
	public boolean hasUserData(String id) throws Exception {
		boolean ret = false;
		Profile profile = LinkedInDB.getProfile(id);
		if (profile != null) {
			ret = true;
		}
		return ret;
	}

	@Override
	public void addUserData(String id) throws Exception {
		//User user = 
		LinkedInDB.toUser(id);
		com.google.code.linkedinapi.schema.Person profile = this.client.getProfileForCurrentUser();
		LinkedInDB.addProfile(id, profile);
		Connections connections = this.client.getConnectionsById(id);
		List<com.google.code.linkedinapi.schema.Person> persons = connections.getPersonList();
		Collection<String> friends = new LinkedList<String>();
		for (com.google.code.linkedinapi.schema.Person person : persons) {
			friends.add(person.getId());
		}
		LinkedInDB.addFriendsOf(id, friends);
	}
	
	@Override
	public Collection<String> getConnections(String id) throws Exception {
		Collection<User> _friends = LinkedInDB.getFriendsOf(id);
		Collection<String> friends = new TreeSet<String>();
		for (User _friend : _friends) {
			friends.add(_friend.getId());
		}
		return friends;
	}

	@Override
	public Person toPerson(String id) throws Exception {
		if (!hasUserData(id)) {
			addUserData(id);
		}
		Person person = null;
		Profile profile = LinkedInDB.getProfile(id);
		if (profile != null ) {
			person = new Person();
			person.setUri("http://semanticlinkedin.example.org/" + profile.getUser());

			final String firstName = profile.getFirstName();
			if (firstName != null) {
				person.addFirstName(firstName);
			}
			
			final String lastName = profile.getLastName();
			if (lastName != null) {
				person.addLastName(lastName);
			}
			
			Collection<User> friends = LinkedInDB.getFriendsOf(id);
			if (friends != null) {
				for (User friend : friends) {
					Person pfriend = new Person();
					pfriend.setUri("http://semanticlinkedin.example.org/" + friend.getId());
					person.addKnows(pfriend);
				}
			}
			
			final String location = profile.getLocation();
			//final String language = (profile.getLanguage() != null ? profile.getLanguage() : "en");
			// XXX
			final String language = "en";
			
			if (location != null) {
				GeoLocation latlng = GeoUtils.findAddLocation(ServiceType.GOOGLE, location, language);
				if (latlng != null) {
					person.setLatitude(BigDecimal.valueOf(latlng.getLatitude()));
					person.setLongitude(BigDecimal.valueOf(latlng.getLongitude()));
				}
			}
		}
		return person;
	}
	
}